/********************************** (C) COPYRIGHT *******************************
 * File Name          : usb_desc.h
 * Author             : WCH
 * Version            : V1.0.0
 * Date               : 2022/08/20
 * Description        : header file of usb_desc.c
 *********************************************************************************
 * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/

#ifndef USER_USB_DESC_H_
#define USER_USB_DESC_H_

#include "debug.h"

/******************************************************************************/
/* global define */
/* file version */
#define DEF_FILE_VERSION 0x0001
/* usb device info define  */
#define DEF_USB_VID 0x1A86
#define DEF_USB_PID 0xFE0C
/* USB device descriptor, device serial number(bcdDevice) */
#define DEF_IC_PRG_VER DEF_FILE_VERSION

/******************************************************************************/
/* usb device endpoint size define */
#define DEF_USBD_UEP0_SIZE 64 /* usb hs/fs device end-point 0 size */
/* FS */
#define DEF_USBD_FS_PACK_SIZE 64       /* usb fs device max bluk/int pack size */
#define DEF_USBD_FS_ISO_PACK_SIZE 1023 /* usb fs device max iso pack size */
/* LS */
#define DEF_USBD_LS_UEP0_SIZE 8  /* usb ls device end-point 0 size */
#define DEF_USBD_LS_PACK_SIZE 64 /* usb ls device max int pack size */

/* Pack size */
#define DEF_USBD_ENDP1_SIZE DEF_USBD_FS_PACK_SIZE
#define DEF_USBD_ENDP2_SIZE DEF_USBD_FS_PACK_SIZE
#define DEF_USBD_ENDP3_SIZE DEF_USBD_FS_PACK_SIZE
#define DEF_USBD_ENDP4_SIZE DEF_USBD_FS_PACK_SIZE
#define DEF_USBD_ENDP5_SIZE DEF_USBD_FS_PACK_SIZE
#define DEF_USBD_ENDP6_SIZE DEF_USBD_FS_PACK_SIZE
#define DEF_USBD_ENDP7_SIZE DEF_USBD_FS_PACK_SIZE
#define USB_STRING_DESCRIPTOR_TYPE 3
/******************************************************************************/
/* usb device Descriptor length, length of usb descriptors, if one descriptor not
 * exists , set the length to 0  */


typedef struct __attribute__ ((packed)) {
    u8 bLength;
    u8 bDescriptorType;
    u16 bcdUSB;
    u8 bDeviceClass;
    u8 bDeviceSubClass;
    u8 bDeviceProtocol;
    u8 bMaxPacketSize0;
    u16 idVendor;
    u16 idProduct;
    u16 bcdDevice;
    u8 iManufacturer;
    u8 iProduct;
    u8 iSerialNumber;
    u8 bNumConfigurations;
} USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;

typedef struct __attribute__ ((packed)) {
    u8 bLength;
    u8 bDescriptorType;
    u16 wTotalLength;
    u8 bNumInterfaces;
    u8 bConfigurationValue;
    u8 iConfiguration;
    u8 bmAttributes;
    u8 MaxPower;
} USB_CONFIGURATION_DESCRIPTOR, *PUSB_CONFIGURATION_DESCRIPTOR;

typedef struct __attribute__ ((packed)) {
    u8 bLength;
    u8 bDescriptorType;
    u8 bFirstInterface;
    u8 bInterfaceCount;
    u8 bFunctionClass;
    u8 bFunctionSubClass;
    u8 bFunctionProtocol;
    u8 iFunction;
} USB_INTERFACE_ASSOCIATION, *PUSB_INTERFACE_ASSOCIATION;

typedef struct __attribute__ ((packed)) {

    u8 bLength;
    u8 bDescriptorType;
    u8 bInterfaceNumber;
    u8 bAlternateSetting;
    u8 bNumEndpoints;
    u8 bInterfaceClass;
    u8 bInterfaceSubClass;
    u8 bInterfaceProtocol;
    u8 iInterface;
} USB_INTERFACE_DESCRIPTOR, *PUSB_INTERFACE_DESCRIPTOR;

typedef struct __attribute__ ((packed)) {
    u8 bLength;
    u8 bDescriptorType;
    u8 bEndpointAddress;
    u8 bmAttributes;
    u16 wMaxPacketSize;
    u8 bInterval;
} USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;

#define USBD_STRDESC_LANGID 0x0409
#define USBD_STRDESC_MAN u"HengTaiSiFang"
#define USBD_STRDESC_PROD u"Loop-Analyzer"
#define USBD_STRDESC_SERIAL u"123456789"
#define USBD_STRDESC_OS u"MSFT100\x0017"

#define USBD_STR_DEF(n)                            \
    struct __attribute__ ((packed, aligned (4))) { \
        u8 len;                                    \
        u8 type;                                   \
        u16 str[sizeof (USBD_##n) / 2 - 1];        \
    } desc##n

#define USBD_STR_VAL(n) \
    { sizeof (USBD_##n), USB_STRING_DESCRIPTOR_TYPE, USBD_##n }


#define USB_COMMUNICATIONS_DESCRIPTOR(x) \
    struct __attribute__ ((packed)) {    \
        u8 bLength;                      \
        u8 bDescriptorType;              \
        u8 bDescriptorSubType;           \
        u8 value[x];                     \
    }

typedef struct __attribute__ ((packed)) {
    USB_CONFIGURATION_DESCRIPTOR configuration;
    // USB_INTERFACE_DESCRIPTOR if0;
    // USB_COMMUNICATIONS_DESCRIPTOR (2)
    // c1;
    // USB_COMMUNICATIONS_DESCRIPTOR (2)
    // c2;
    // USB_COMMUNICATIONS_DESCRIPTOR (1)
    // c3;
    // USB_COMMUNICATIONS_DESCRIPTOR (2)
    // c4;
    // USB_ENDPOINT_DESCRIPTOR ep0;
    USB_INTERFACE_DESCRIPTOR if0;
    USB_ENDPOINT_DESCRIPTOR ep1;
    USB_ENDPOINT_DESCRIPTOR ep2;
} USBConfiguration, *PUSBConfiguration;

typedef struct {
    struct __attribute__ ((packed)) {
        u8 len;
        u8 type;
        u16 Langid;
    } desc_langid;

    USBD_STR_DEF (STRDESC_MAN);
    USBD_STR_DEF (STRDESC_PROD);
    USBD_STR_DEF (STRDESC_SERIAL);
    USBD_STR_DEF (STRDESC_OS);
} USBD_StringDescriptor;

/******************************************************************************/
/* external variables */
extern const USB_DEVICE_DESCRIPTOR MyDevDescr;

extern const USBConfiguration MyCfgDescr;

extern const USBD_StringDescriptor stringDescriptors;
extern const u8 winUSB[];
#endif /* USER_USB_DESC_H_ */
